package course_signup

import (
	"context"
	"net/http"
	"time"

	"encoding/json"

	"strconv"
	"go.uber.org/zap"

	"internal_training_be/db"
	"internal_training_be/user_mgt"
)

func Run (){

	zap.L().Sugar().Info("---->course_signup/course_signup.go is run")

	employeeMiddlewares := user_mgt.EmployeeImpl{}

	adminMiddlewares := user_mgt.AdminImpl{}

	http.Handle("/api/courseSignUp",employeeMiddlewares.CorsMiddleware(employeeMiddlewares.AuthMiddleware(http.HandlerFunc(courseSignUp))))

	http.Handle("/api/courseSignUpCancel",employeeMiddlewares.CorsMiddleware(employeeMiddlewares.AuthMiddleware(http.HandlerFunc(courseSignUpCancel))))

	http.Handle("/api/signUpStatusQuery", adminMiddlewares.CorsMiddleware(adminMiddlewares.AuthMiddleware(http.HandlerFunc(querySignupData))))
}

func checkCourseNum(courseID string, ctx context.Context) (int, error){

	zap.L().Sugar().Info("---->course_signup/checkCourseNum")

	// 查询课程表中课程的剩余名额
	var courseNum int

	// 获取数据库连接
	dbConn, err := db.GetDBConn()
	if err != nil {
		zap.L().Sugar().Errorf("获取数据库连接失败, err: %v", err.Error())
		return -1, err
	}

	if dbConn == nil {
		zap.L().Sugar().Error("获取数据库连接失败, dbConn为空")
		return -1, err
	}

	err = dbConn.QueryRow(context.Background(), `SELECT number FROM s_training_system.t_course WHERE id = $1`, courseID).Scan(&courseNum)

	defer dbConn.Release()

	if err != nil {
		zap.L().Sugar().Error("查询课程表中课程的剩余名额失败, err: " + err.Error())
		return -1, err
	}

	return courseNum, nil
}

func courseSignUp(w http.ResponseWriter, r *http.Request) {

	zap.L().Sugar().Info("---->course_signup/courseSignUp")

	var msg string
	
	// 读取请求上下文
	ctx := r.Context()	

	// 获取员工ID
	employeeID := ctx.Value("employId").(string)

	if employeeID == "" {
		zap.L().Sugar().Error("获取员工ID为空")
		return
	}

	var rBody struct {
		CourseID string `json:"courseID"`
	}

	// 获取请求体中的课程ID
	err := json.NewDecoder(r.Body).Decode(&rBody)
	if err != nil {
		msg = `解析请求体发生错误,未找到"courseID"字段,err: ` + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	} 

	// 查询课程表中课程的剩余名额
	courseNum, err := checkCourseNum(rBody.CourseID, ctx)
	if err != nil {
		msg = "查询课程表中课程的剩余名额失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	if courseNum <= 0 {
		msg = "报名失败,课程名额已满！"
		zap.L().Sugar().Info(msg, "用户ID: ", employeeID)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 获取数据库连接
	dbConn, err := db.GetDBConn()
	if err != nil {
		zap.L().Sugar().Errorf("获取数据库连接失败, err: %v", err.Error())
		return
	}

	if dbConn == nil {
		zap.L().Sugar().Error("获取数据库连接失败, dbConn为空")
		return
	}

	defer dbConn.Release()

	// 查询t_enrollment表中是否已经报名
	var count int
	err = dbConn.QueryRow(context.Background(), `SELECT COUNT(*) FROM s_training_system.t_enrollment WHERE employee_id = $1 AND course_id = $2`, employeeID, rBody.CourseID).Scan(&count)
	if err != nil {
		msg = "查询报名表中是否已经报名失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	if count > 0 {
		msg = "您已经报名该课程！"
		zap.L().Sugar().Info(msg, "用户ID: ", employeeID)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 获取当前时间戳作为报名ID
	signUpID := time.Now().Unix()

	// 将报名ID转成字符串
	signUpIDStr := strconv.FormatInt(signUpID, 10)

	// 向数据库t_enrollment表中插入数据
	_, err = dbConn.Exec(r.Context(), `INSERT INTO s_training_system.t_enrollment (id, employee_id, course_id, status) VALUES ($1,$2,$3,$4)`, signUpIDStr, employeeID, rBody.CourseID, 1)

	if err != nil {
		msg = "报名失败, err: " + err.Error()
		zap.L().Sugar().Error(`向报名表中插入数据失败，err: ` + err.Error())
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 更新课程表中的剩余名额
	_, err = dbConn.Exec(r.Context(), `UPDATE s_training_system.t_course SET number = number - 1 WHERE id = $1`, rBody.CourseID)
	if err != nil {
		msg = "更新课程表中的剩余名额失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 报名成功
	msg = "报名成功！"

	json.NewEncoder(w).Encode(map[string]interface{}{
		"msg": msg,
		"code": 0,
	})

}

func courseSignUpCancel(w http.ResponseWriter, r *http.Request) {

	zap.L().Sugar().Info("---->course_signup/courseSignUpCancel")

	var msg string
	
	// 读取请求上下文
	ctx := r.Context()	

	// 获取员工ID
	employeeID := ctx.Value("employId").(string)

	if employeeID == "" {
		zap.L().Sugar().Error("获取员工ID为空")
		return
	}

	var rBody struct {
		CourseID string `json:"courseID"`
	}

	// 获取请求体中的课程ID
	err := json.NewDecoder(r.Body).Decode(&rBody)
	if err != nil {
		msg = `解析请求体发生错误,未找到"courseID"字段,err: ` + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	} 

	// 获取数据库连接
	dbConn, err := db.GetDBConn()
	if err != nil {
		zap.L().Sugar().Errorf("获取数据库连接失败, err: %v", err.Error())
		return
	}

	if dbConn == nil {
		zap.L().Sugar().Error("获取数据库连接失败, dbConn为空")
		return
	}

	defer dbConn.Release()

	// 查询t_enrollment表中是否已经报名
	var count int
	err = dbConn.QueryRow(context.Background(), `SELECT COUNT(*) FROM s_training_system.t_enrollment WHERE employee_id = $1 AND course_id = $2`, employeeID, rBody.CourseID).Scan(&count)
	if err != nil {
		msg = "查询报名表中是否已经报名失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	if count == 0 {
		msg = "您还未报名该课程！"
		zap.L().Sugar().Info(msg, "用户ID: ", employeeID)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 从t_enrollment表中删除数据
	_, err = dbConn.Exec(r.Context(), `DELETE FROM s_training_system.t_enrollment WHERE employee_id = $1 AND course_id = $2`, employeeID, rBody.CourseID)
	if err != nil {
		msg = "取消报名失败, err: " + err.Error()
		zap.L().Sugar().Error(`从报名表中删除数据失败，err: ` + err.Error())
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 更新课程表中的剩余名额
	_, err = dbConn.Exec(r.Context(), `UPDATE s_training_system.t_course SET number = number + 1 WHERE id = $1`, rBody.CourseID)
	if err != nil {
		msg = "更新课程表中的剩余名额失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 取消报名成功
	msg = "取消报名成功！"

	json.NewEncoder(w).Encode(map[string]interface{}{
		"msg": msg,
		"code": 0,
	})

}

func querySignupData(w http.ResponseWriter, r *http.Request) {

	zap.L().Sugar().Info("---->course_signup/querySignupData")

	var msg string

	// 读取请求上下文
	ctx := r.Context()

	// 获取管理员ID
	adminID := ctx.Value("adminId").(string)

	if adminID == "" {
		zap.L().Sugar().Error("获取管理员ID为空")
		return
	}

	var rBody struct {
		CourseID string `json:"courseID"`
	}

	// 获取请求体中的课程ID
	err := json.NewDecoder(r.Body).Decode(&rBody)
	if err != nil {
		msg = `解析请求体发生错误,未找到"courseID"字段,err: ` + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	// 获取数据库连接
	dbConn, err := db.GetDBConn()
	if err != nil {
		zap.L().Sugar().Errorf("获取数据库连接失败, err: %v", err.Error())
		return
	}

	if dbConn == nil {
		zap.L().Sugar().Error("获取数据库连接失败, dbConn为空")
		return
	}

	defer dbConn.Release()

	// 获取t_enrollment表中的报名数据
	rows, err := dbConn.Query(context.Background(), `SELECT * FROM s_training_system.t_enrollment WHERE course_id = $1`, rBody.CourseID)
	if err != nil {
		msg = "查询报名表中的报名数据失败, err: " + err.Error()
		zap.L().Sugar().Error(msg)
		json.NewEncoder(w).Encode(map[string]interface{}{
			"msg": msg,
			"code": 1,
		})
		return
	}

	var signUpData []map[string]interface{}

	for rows.Next() {
		var signUpID string
		var employeeID string
		var courseID string
		var status int
		err = rows.Scan(&signUpID, &employeeID, &courseID, &status)
		if err != nil {
			msg = "读取报名数据失败, err: " + err.Error()
			zap.L().Sugar().Error(msg)
			json.NewEncoder(w).Encode(map[string]interface{}{
				"msg": msg,
				"code": 1,
			})
			return
		}

		var employeeName string

		// 获取数据库连接
		dbConn, err = db.GetDBConn()
		if err != nil {
			zap.L().Sugar().Errorf("获取数据库连接失败, err: %v", err.Error())
			return
		}

		if dbConn == nil {
			zap.L().Sugar().Error("获取数据库连接失败, dbConn为空")
			return
		}

		defer dbConn.Release()
		
		err := dbConn.QueryRow(context.Background(), `SELECT username FROM s_training_system.t_employee WHERE id = $1`, employeeID).Scan(&employeeName)
		if err != nil {
			msg = "查询员工姓名失败, err: " + err.Error()
			zap.L().Sugar().Error(msg)
			continue
		}

		var courseName string

		err = dbConn.QueryRow(context.Background(), `SELECT name FROM s_training_system.t_course WHERE id = $1`, courseID).Scan(&courseName)
		if err != nil {
			msg = "查询课程名称失败, err: " + err.Error()
			zap.L().Sugar().Error(msg)
			continue
		}

		signUpData = append(signUpData, map[string]interface{}{
			"signUpID": signUpID,
			"employeeID": employeeID,
			"employeeName": employeeName,
			"courseID": courseID,
			"courseName": courseName,
			"statusCode": status,
		})
	}

	json.NewEncoder(w).Encode(map[string]interface{}{
		"msg": "查询报名数据成功！",
		"code": 0,
		"data": signUpData,
	})

}